#include "updatemanager.h"
#include "configmanager.h"
#include <QNetworkRequest>
#include <QStandardPaths>
#include <QDir>
#include <QCryptographicHash>
#include <QJsonDocument>
#include <QJsonObject>
#include <QApplication>
#include <QMessageBox>
#include <QProcess>
#include <QDebug>
#include <QMimeDatabase>
#include <QRegularExpression>
#include <QDesktopServices>

// 重试延迟配置（毫秒）
const int UpdateManager::RETRY_DELAYS[MAX_RETRY_COUNT] = {1000, 3000, 5000};

UpdateManager::UpdateManager(QObject* parent)
    : QObject(parent)
    , m_networkManager(new QNetworkAccessManager(this))
    , m_currentReply(nullptr)
    , m_outputFile(nullptr)
    , m_isDownloading(false)
    , m_isPaused(false)
    , m_downloadProgress(0)
    , m_downloadSpeed("0 B/s")
    , m_downloadStartTime(0)
    , m_lastReceivedBytes(0)
    , m_retryTimer(new QTimer(this))
    , m_retryCount(0)
{

    // 设置重试定时器
    m_retryTimer->setSingleShot(true);
    connect(m_retryTimer, &QTimer::timeout, this, &UpdateManager::onRetryTimer);

    // 检查并创建下载目录
    createDownloadDirectory();
}

UpdateManager::~UpdateManager()
{
    if (m_currentReply) {
        m_currentReply->abort();
        m_currentReply->deleteLater();
    }
    if (m_outputFile) {
        m_outputFile->close();
        m_outputFile->deleteLater();
    }
}

void UpdateManager::checkForUpdates(bool silent)
{

    m_retryCount = 0;
    checkServerVersion();
}

void UpdateManager::checkServerVersion()
{

    // 如果用户已登录，通过登录API检查版本
    QString token = ConfigManager::getUserToken();
    if (!token.isEmpty()) {
        // 构建登录请求检查版本
        QJsonObject payload;
        payload["email"] = ConfigManager::getUserEmail();
        payload["deviceName"] = ConfigManager::getDeviceName();
        payload["currentVersion"] = ConfigManager::getCurrentVersion();
        payload["platform"] = VersionManager::getCurrentPlatform();

        QJsonDocument doc(payload);
        QByteArray data = doc.toJson();

        // 使用SecureApiManager的当前端点构建登录URL
        SecureApiManager& apiManager = SecureApiManager::instance();
        QString currentEndpoint = apiManager.getCurrentEndpoint();
        QString loginUrl = currentEndpoint + "/auth/client/login";

        QNetworkRequest request((QUrl(loginUrl)));
        request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json; charset=utf-8");
        request.setHeader(QNetworkRequest::UserAgentHeader, LimeReader::AppVersion::getUserAgent());
        request.setRawHeader("Accept", "application/json");

        // 添加认证Token到请求头
        if (!token.isEmpty()) {
            request.setRawHeader("Authorization", QString("Bearer %1").arg(token).toUtf8());
        }

        if (m_currentReply) {
            m_currentReply->abort();
            m_currentReply->deleteLater();
        }

        m_currentReply = m_networkManager->post(request, data);
        connect(m_currentReply, &QNetworkReply::finished, this, &UpdateManager::onRequestFinished);

    } else {
    }
}

void UpdateManager::onRequestFinished()
{
    if (!m_currentReply) return;

    QByteArray response = m_currentReply->readAll();
    int statusCode = m_currentReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();


    if (m_currentReply->error() != QNetworkReply::NoError) {
        QString errorString = m_currentReply->errorString();

        if (m_retryCount < MAX_RETRY_COUNT) {
            scheduleRetry();
        } else {
            handleError(tr("检查更新失败：%1").arg(errorString));
        }
        m_currentReply->deleteLater();
        m_currentReply = nullptr;
        return;
    }

    // 解析JSON响应
    QJsonParseError parseError;
    QJsonDocument doc = QJsonDocument::fromJson(response, &parseError);

    if (parseError.error != QJsonParseError::NoError) {
        handleError(tr("服务器响应格式错误"));
        m_currentReply->deleteLater();
        m_currentReply = nullptr;
        return;
    }

    QJsonObject jsonResponse = doc.object();
    parseLoginResponse(jsonResponse);

    m_currentReply->deleteLater();
    m_currentReply = nullptr;
}

void UpdateManager::parseLoginResponse(const QJsonObject& jsonResponse)
{

    // 更新用户信息
    if (jsonResponse.contains("token")) {
        ConfigManager::setUserToken(jsonResponse["token"].toString());
    }

    // 解析更新信息
    QString currentVersion = ConfigManager::getCurrentVersion();
    QString platform = VersionManager::getCurrentPlatform();

    m_currentUpdateInfo = VersionManager::parseUpdateInfo(jsonResponse, currentVersion, platform);

    if (m_currentUpdateInfo.hasUpdate) {

        // 更新服务器版本显示
        emit serverVersionReceived(m_currentUpdateInfo.latestVersion.toString());

        // 检查是否应该跳过此版本
        QString skippedVersion = ConfigManager::getSkippedVersion();
        if (!VersionManager::shouldSkipVersion(m_currentUpdateInfo, skippedVersion)) {
            emit updateAvailable(m_currentUpdateInfo);
        } else {
        }
    } else {
        emit serverVersionReceived(currentVersion);
    }
}

void UpdateManager::startUpdate()
{
    if (!m_currentUpdateInfo.hasUpdate) {
        return;
    }

    if (m_isDownloading) {
        return;
    }


    m_isDownloading = true;
    m_isPaused = false;
    m_downloadProgress = 0;
    m_downloadStartTime = QDateTime::currentMSecsSinceEpoch();
    m_lastReceivedBytes = 0;

    // 准备下载文件
    m_downloadPath = getDownloadPath();
    if (m_outputFile) {
        m_outputFile->close();
        m_outputFile->deleteLater();
    }

    m_outputFile = new QFile(m_downloadPath);
    if (!m_outputFile->open(QIODevice::WriteOnly)) {
        handleError(tr("无法创建下载文件：%1").arg(m_downloadPath));
        m_isDownloading = false;
        return;
    }

    // 开始下载
    QUrl url(m_currentUpdateInfo.updateUrl);
    QNetworkRequest request(url);
    request.setHeader(QNetworkRequest::UserAgentHeader, LimeReader::AppVersion::getUserAgent());

    if (m_currentReply) {
        m_currentReply->abort();
        m_currentReply->deleteLater();
    }

    m_currentReply = m_networkManager->get(request);
    connect(m_currentReply, &QNetworkReply::downloadProgress, this, &UpdateManager::onDownloadProgress);
    connect(m_currentReply, &QNetworkReply::finished, this, &UpdateManager::onDownloadFinished);
}

void UpdateManager::onDownloadProgress(qint64 received, qint64 total)
{
    if (total <= 0) return;

    // 计算进度百分比
    m_downloadProgress = static_cast<int>((received * 100) / total);

    // 计算下载速度
    qint64 currentTime = QDateTime::currentMSecsSinceEpoch();
    qint64 timeDiff = currentTime - m_downloadStartTime;
    if (timeDiff > 0) {
        qint64 bytesDiff = received - m_lastReceivedBytes;
        qint64 speed = (bytesDiff * 1000) / timeDiff; // bytes per second

        if (speed < 1024) {
            m_downloadSpeed = QString("%1 B/s").arg(speed);
        } else if (speed < 1024 * 1024) {
            m_downloadSpeed = QString("%1 KB/s").arg(speed / 1024.0, 0, 'f', 1);
        } else {
            m_downloadSpeed = QString("%1 MB/s").arg(speed / (1024.0 * 1024.0), 0, 'f', 1);
        }

        // 每秒更新一次速度计算
        if (timeDiff > 1000) {
            m_downloadStartTime = currentTime;
            m_lastReceivedBytes = received;
        }
    }

    // 写入下载的数据
    if (m_outputFile && m_outputFile->isOpen()) {
        QByteArray data = m_currentReply->readAll();
        m_outputFile->write(data);
    }

    emit downloadProgress(m_downloadProgress, received, total);

}

void UpdateManager::onDownloadFinished()
{
    if (!m_currentReply) return;

    if (m_currentReply->error() != QNetworkReply::NoError) {
        QString errorString = m_currentReply->errorString();
        handleError(tr("下载失败：%1").arg(errorString));
        cleanupDownload();
        return;
    }

    // 完成文件写入
    if (m_outputFile && m_outputFile->isOpen()) {
        QByteArray remainingData = m_currentReply->readAll();
        m_outputFile->write(remainingData);
        m_outputFile->close();
    }


    // 验证文件
    if (!verifyDownloadedFile(m_downloadPath)) {
        handleError(tr("下载文件验证失败"));
        cleanupDownload();
        return;
    }

    m_isDownloading = false;
    emit downloadFinished(m_downloadPath);

    // 自动执行更新
    performUpdate(m_downloadPath);
}

void UpdateManager::onDownloadError(QNetworkReply::NetworkError error)
{
    QString errorMessage = getErrorMessage(error);

    if (m_retryCount < MAX_RETRY_COUNT) {
        scheduleRetry();
    } else {
        handleError(tr("下载失败：%1").arg(errorMessage));
        cleanupDownload();
    }
}

bool UpdateManager::verifyDownloadedFile(const QString& filePath)
{

    QFile file(filePath);
    if (!file.exists()) {
        return false;
    }

    // 验证文件大小
    qint64 fileSize = file.size();
    if (fileSize < 1024 * 1024) { // 小于1MB可能有问题
        return false;
    }

    // 验证MD5校验和（如果提供）
    if (!m_currentUpdateInfo.checksumMD5.isEmpty()) {
        QString calculatedMD5 = calculateMD5(filePath);
        if (calculatedMD5 != m_currentUpdateInfo.checksumMD5) {
            return false;
        }
    }

    return true;
}

QString UpdateManager::calculateMD5(const QString& filePath)
{
    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly)) {
        return QString();
    }

    QCryptographicHash hash(QCryptographicHash::Md5);
    while (!file.atEnd()) {
        hash.addData(file.read(8192));
    }

    return hash.result().toHex();
}

void UpdateManager::performUpdate(const QString& filePath)
{

#ifdef Q_OS_WIN
    // Windows: 打开下载目录，提示用户手动安装
    QString downloadDir = QFileInfo(filePath).absolutePath();
    QDesktopServices::openUrl(QUrl::fromLocalFile(downloadDir));

    QMessageBox::information(nullptr, tr("更新下载完成"),
        tr("更新包已下载完成！\n\n请手动运行安装程序完成更新。\n\n文件位置：%1").arg(filePath));
#else
    // macOS: 打开DMG文件
    QDesktopServices::openUrl(QUrl::fromLocalFile(filePath));

    QMessageBox::information(nullptr, tr("更新下载完成"),
        tr("更新包已下载完成！\n\n请打开DMG文件并按照提示完成更新。"));
#endif

    emit updateFinished(true);
}

void UpdateManager::pauseDownload()
{
    if (m_isDownloading && !m_isPaused) {
        m_isPaused = true;
        if (m_currentReply) {
            m_currentReply->abort();
        }
    }
}

void UpdateManager::resumeDownload()
{
    if (m_isPaused) {
        m_isPaused = false;
        startUpdate(); // 重新开始下载
    }
}

void UpdateManager::cancelUpdate()
{
    if (m_isDownloading) {
        m_isDownloading = false;
        m_isPaused = false;

        if (m_currentReply) {
            m_currentReply->abort();
            m_currentReply->deleteLater();
            m_currentReply = nullptr;
        }

        cleanupDownload();
    }
}

bool UpdateManager::hasUpdateAvailable() const
{
    return m_currentUpdateInfo.hasUpdate;
}

VersionManager::UpdateInfo UpdateManager::getUpdateInfo() const
{
    return m_currentUpdateInfo;
}

QString UpdateManager::getDownloadPath() const
{
    QString downloadDir = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
    if (downloadDir.isEmpty()) {
        downloadDir = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
    }

    QString fileName = VersionManager::getUpdateFileName(m_currentUpdateInfo.latestVersion, m_currentUpdateInfo.platform);
    return QDir(downloadDir).absoluteFilePath(fileName);
}

bool UpdateManager::createDownloadDirectory()
{
    QString downloadDir = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
    if (downloadDir.isEmpty()) {
        downloadDir = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
    }

    QDir dir(downloadDir);
    if (!dir.exists()) {
        bool created = dir.mkpath(downloadDir);
        return created;
    }

    return true;
}

void UpdateManager::cleanupDownload()
{
    m_isDownloading = false;
    m_isPaused = false;

    if (m_outputFile) {
        m_outputFile->close();
        m_outputFile->deleteLater();
        m_outputFile = nullptr;
    }

    if (m_currentReply) {
        m_currentReply->deleteLater();
        m_currentReply = nullptr;
    }
}

void UpdateManager::handleError(const QString& error)
{
    emit downloadError(error);
}

void UpdateManager::scheduleRetry()
{
    m_retryCount++;
    int delay = RETRY_DELAYS[m_retryCount - 1];


    m_retryTimer->start(delay);
}

void UpdateManager::onRetryTimer()
{

    if (m_isDownloading) {
        startUpdate(); // 重新开始下载
    } else {
        checkServerVersion(); // 重新检查版本
    }
}

QString UpdateManager::getErrorMessage(QNetworkReply::NetworkError error)
{
    switch (error) {
    case QNetworkReply::ConnectionRefusedError:
        return tr("连接被拒绝");
    case QNetworkReply::RemoteHostClosedError:
        return tr("远程主机关闭连接");
    case QNetworkReply::HostNotFoundError:
        return tr("找不到主机");
    case QNetworkReply::TimeoutError:
        return tr("连接超时");
    case QNetworkReply::OperationCanceledError:
        return tr("操作被取消");
    case QNetworkReply::SslHandshakeFailedError:
        return tr("SSL握手失败");
    case QNetworkReply::TemporaryNetworkFailureError:
        return tr("临时网络故障");
    case QNetworkReply::NetworkSessionFailedError:
        return tr("网络会话失败");
    case QNetworkReply::BackgroundRequestNotAllowedError:
        return tr("不允许后台请求");
    case QNetworkReply::TooManyRedirectsError:
        return tr("重定向次数过多");
    case QNetworkReply::InsecureRedirectError:
        return tr("不安全的重定向");
    case QNetworkReply::ProxyConnectionRefusedError:
        return tr("代理连接被拒绝");
    case QNetworkReply::ProxyConnectionClosedError:
        return tr("代理连接关闭");
    case QNetworkReply::ProxyNotFoundError:
        return tr("找不到代理");
    case QNetworkReply::ProxyTimeoutError:
        return tr("代理超时");
    case QNetworkReply::ProxyAuthenticationRequiredError:
        return tr("代理需要认证");
    case QNetworkReply::ContentAccessDenied:
        return tr("访问被拒绝");
    case QNetworkReply::ContentOperationNotPermittedError:
        return tr("操作不被允许");
    case QNetworkReply::ContentNotFoundError:
        return tr("找不到内容");
    case QNetworkReply::AuthenticationRequiredError:
        return tr("需要认证");
    case QNetworkReply::ContentReSendError:
        return tr("需要重新发送内容");
    case QNetworkReply::ContentConflictError:
        return tr("内容冲突");
    case QNetworkReply::ContentGoneError:
        return tr("内容已移除");
    case QNetworkReply::InternalServerError:
        return tr("服务器内部错误");
    case QNetworkReply::OperationNotImplementedError:
        return tr("操作未实现");
    case QNetworkReply::ServiceUnavailableError:
        return tr("服务不可用");
    case QNetworkReply::ProtocolUnknownError:
        return tr("未知协议");
    case QNetworkReply::ProtocolFailure:
        return tr("协议失败");
    default:
        return tr("未知网络错误");
    }
}

void UpdateManager::cleanDownloadFiles()
{
    // 清理旧的下载文件（可选实现）
}